home *** CD-ROM | disk | FTP | other *** search
-
- ========================================================================
- Just4Fun Productions presents:
-
- Part 1 of: the Techtutor
- (Topics never covered)
-
-
- Bullets Handling
- ========================================================================
-
- Introduction
- ============-
- Welcome to the first of these tech files... These files were originally only
- on the homepage of Just4Fun Productions, but I tought they deserved to have
- a more public audience, so here it is!
- Since I allready had these files completed, the first few are released on
- the same date, so if you downloaded this from some place, you should be able
- to get the next few at that same place (I uploaded them atleast to x2ftp).
-
- The topics I'll cover are not the normal demo tutors, or vga trainers (get
- the tutors from Telemachos and Denthor for that, they'r good!)
- I'll cover the game-programming topics that are never explained (at least
- not to my knowledge...), things I'll cover are for some simple things, but
- for alot of other people very difficult to do. Most topics are useable in 2D
- games and 3D games, but since I still like the 2D games my code is also
- focused on those type of games.
-
- Most of the code I talk about in these files will also be extracted from the
- SuperFX engine, a freeware engine I created for 2D games...you can download
- it from the Just4Fun homepage (http://people.zeelandnet.nl/rpb).
- Also I must tell you that the example code doesn't allways work just like
- that, you might have to add things or change things...the hard stuff is
- usually working though..
-
-
- ----------------------------------------------------------------
- For contacting Just4Fun or me (PeeBee) use the following ways:
-
- Internet : http://people.zeelandnet.nl/rpb
- Email : just4fun@zeelandnet.nl
-
- SnailMail: P.Bestebroer
- Anthony Edenlaan 28
- 4463 JC Goes (Zld.)
- Holland
-
- ICQ : 2309110 (probably fastest way to contact me)
- ----------------------------------------------------------------
-
-
-
-
- Lets Start This!
- ================-
-
- Now let's talk about bullets, they'r very important in most games
- but how could we program them? First let's see what a bullet does in the
- game:
- * It's shot by the player or enemies
- * It flies a certain path until it hits something
- * If it hits an enemy then kill it, and erase the bullet
- * if it hits a wall erase the bullet.
-
- This list shows that a bullet is only active for a short period so creating
- an array would not be that efficient.
-
-
- We need a linked-list!
- ======================-
-
- The best way for bullets would be to create a linked-list. For those of
- you who don't know what this is, here's some information:
-
- A linked list is composed of pointers. You'll need at least two pointers
- one will be the first, pointing to the first item in the list, and
- the second will be the last, pointing to...exactly the last item.
-
- Now the item it points to can be any variable you want, but using
- a RECORD would be best in the case of bullets. Here's an example of
- defining the linked-list:
-
- TYPE PBullet = ^TBullet;
- TYPE TBullet = record
- xposition : word;
- yposition : word;
- previous : PBullet;
- next : PBullet;
- END;
-
- VAR FirstBullet : PBullet;
- LastBullet : PBullet;
-
- Let's explain this. The first type "PBULLET" is a pointer type of
- the Tbullet record, so that's used for the linked-list. The variables
- xposition/yposition explain them selves, but the previous/next variables are
- the main thing for the linked-list. They point to the previous/next item in
- the linked list! So let's say we've got 5 bullets flying around.
- Our list would look like:
-
- FirstBullet = Bullet(1)
- Bullet(1).Previous = NIL { No bullet infront of bullet 1 ! }
- Bullet(1).Next = Bullet(2) { pointer to next bullet }
- Bullet(2).Previous = Bullet(1) { The previous bullet is bullet 1 }
- Bullet(2).Next = Bullet(3) { pointer to next bullet = 3 }
- ....
- LastBullet = Bullet(5) { the lastbullet is bullet(5) }
- Bullet(5).Previous = Bullet(4) { the previous bullet is bullet 4 }
- Bullet(5).Next = NIL { there are no more bullets }
-
- That's all the information about "linked-list" I'll give here, just
- find some more and bether examples if you still don't get it (there are
- enough books explaining it, and there should be some nice text files on the
- internet somewhere).
-
-
- How do we create the bullets?
- =============================-
-
- Bullet's will never be "there" all the time, so they have to be
- created as soon as the player hits FIRE, and erase as soon as they
- hit something. For this purpose we'll need a small procedure that will
- add a new bullet to the linked-list. The procedure that does this is called
- ADDBULLET, it's only purpose is to "initialise" a new bullet by adding it to
- the linked-list. Once the bullet is added it will be processed by the
- DOBULLETS procedure. The ADDBULLET procedure needs some information about
- the position of the bullet, the person who shot it (player/enemy)
- the BULLET-AI (ie. a rocket, shell, grenade, etc...). The speed of the
- bullet, the image-frame (sprite) the bullet uses, and maybe some specific
- things for you'r game, but that's upto you.
-
- {=-=-= Example =-=-=}
- FUNCTION AddBullet( Xpos2,Ypos2,xspeed2,yspeed2 : integer;
- F_Frame2,ai2,subai2 : byte):boolean;
- VAR TempBull : PBullet; { this is used to create the new-bullet }
- BEGIN
- AddBullet:=false; { No bullet is added upto this point }
-
- new(TempBull); { Get memory for new bullet }
-
- if TempBull=nil then exit; { if TEMP=NIL, we don't have enough memory }
-
- if FirstBullet=NIL then begin { is the list empty? }
- LastBullet:=TempBull; { yes, so the NEW-BULLET is the first+last }
- FirstBullet:=TempBull;
- with FirstBullet^ do begin
- next:=NIL; { next/previous are nothing, because there }
- prev:=Nil; { is only one bullet in the list }
- end;
- end else begin { More bullets in the list! }
- LastBullet^.next:=tempbull;{ Lastbullet points to new-bullet }
- TempBull^.prev:=LastBullet;{ lastbullet is not lastbullet anymore }
- LastBullet:=TempBull; { Lastbullet=NEWBULLET }
- Tempbull^.next:=NIL; { no bullets after the new-bullet }
- end;
-
- With TempBull^ do begin { Set the new values }
- xpos:=xpos2+xspeed2;
- ypos:=ypos2+yspeed2;
- xspeed:=xspeed2;
- yspeed:=yspeed2;
-
- ai :=ai2;
- subai :=subai2;
- f_Frame :=f_Frame2;
- end;
-
- AddBullet:=True; { the bullet was added }
- END;
- {=-=-= End of Example =-=-=-=}
-
- What the ADDBULLET procedure does is this:
- * Create a new pointer to a bullet-type
- * Update LASTBULLET and FIRSTBULLET pointers if necessary.
- * set the new-bullet variables to the ones specified (xpos, ypos,speed...)
- Now a new bullet is added to the linked-list...
-
-
- I believe it can fly
- ====================-
-
- Now we have a bullet in the list, but we still have to make it work.
- To do this, we call the DOBULLETS procedure every frame. What the DOBULLETS
- procedure does is:
-
- * Get pointer of FIRSTBULLET.
- * Update Xposition, Yposition, animation, energy, etc...
- * Check if bullet hits something, and take action
- * Draw bullet on screen
- * Go to next bullet in the list, until LASTBULLET is reached.
-
- {=-=-= Example =-=-=-=}
- PROCEDURE DoBullets;
- VAR temp : PBullet; { temporary bullet }
- next_Bull : PBullet; { next bullet in list }
- done : boolean; { bullet done? }
- BEGIN
- Temp:=FirstBullet; { start with first bullet }
-
- WHILE Temp<>Nil do begin { while not pointing to NIL, do bullets }
- with Temp^ do begin
- done:=false; { bullet not yet done }
- next_Bull:=temp^.next; { pointer to Next-bullet in list }
-
- Case AI of { check on bullet AI }
- 1 : BEGIN { normal bullet }
- inc(xpos,xspeed); { increase X position }
- inc(ypos,yspeed); { increase Y position }
- {
- ....
- Check boundaries of screen
- and check for wall-background blocks
- ....
- }
- { Bullet hits something, or is off-screen }
- if not EraseBullet(temp) then begin
- { ERROR! bullet could not be disposed }
- halt(1);
- end;
- Done:=True; { Bullet is done }
- END;
- END;{CASE ai }
-
- { if bullet was not "erased" continue the procedure }
- If Not done then begin { see if we hit the player }
- {
- ....
- See if bullet is not shot by player
- ....
- }
- {
- ....
- Check with player coordinates
- ....
- }
- { IF HIT PLAYER THEN BEGIN }
- { Bullet hits player, and is erased }
- if not EraseBullet(temp) then begin
- { ERROR! bullet could not be disposed }
- halt(1);
- end;
- done:=true;
- end;
- { if bullet was not "erased" continue the procedure }
- if not done then
- {
- ....
- Draw the image on the screen!
- ....
- }
- end;
- temp:=next_Bull; { get pointer to next bullet in the list }
- end;
- END;
- {=-=-= End of Example =-=-=}
-
- This should make the bullets fly around, BUT we DO check if the bullet
- hits something, but we should allso erase it from the linked-list.
- For erasing it we need the third procedure called ERASEBULLET.
-
-
- Kill, Kill, Kill the bullet
- ===========================-
-
- Question: Why do we need to erase the bullet, can't we just leave it, and
- not draw it?
- Answer : No, because it stopped existing, and we need the memory it
- uses.
-
- By erasing the bullet from the linked-list, you'll also free up the
- memory occupied by it and that is the power of linked-lists.
- So how do we erase it? Well let's see what ERASEBULLET does:
-
- * When calling it, specify the pointer to the BULLET
- * Simply erase it from memory,
- * and update the list-pointers.
-
- {=-=-= Example =-=-=}
- FUNCTION EraseBullet(Temp:PBullet):boolean;
- VAR next_bull,
- prev_bull : PBullet;
- BEGIN
- EraseBullet:=false; { bullet not yet erased }
- if Temp=NIL then exit; { if bullet=NIL then just exit }
-
- prev_BULL:=Temp^.prev; { Correct the bullet pointers }
- next_BULL:=Temp^.next;
-
- if prev_BULL=NIL then begin { if there is no previous bullet, then }
- FirstBullet:=next_Bull; { we'r working with the firstbullet }
- end else
- Prev_bull^.next:=next_bull;
-
- if next_bull=NIL then begin { if there is no next bullet , then }
- LastBullet:=prev_Bull; { we'r working with the lastbullet }
- end else
- Next_Bull^.prev:=prev_Bull;
-
- dispose(Temp); { dispose the bullet, freeing up memory }
- END;
- {=-=-= End of Example =-=-=}
-
- That's it!
- ==========-
-
- Well this was the bullet-code in a fast way, but just take a look at
- the supplied example code, and you should be able to do it your self.
- If you got some questions about the bullets, just email me and I'll try to
- answer you'r question.
-
- The next Tech file is about handling aliens, objects and bonus things...
-
- If you want to know about some other game-related code, mail me aswell,
- and I might create a new TECH file, trust me I'm really that nice!
-
-
- PeeBee - September 10th '97
-